﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;
using Bejeweled.Support;
using Bejeweled.Manager;
using System.Threading;

namespace Bejeweled.Manager
{
    public class EntityManager : Microsoft.Xna.Framework.DrawableGameComponent
    {
            // text will be showed
          string TEXT = "SCORE: ";
          int time = 0;
          //public int point;
          // graphic device manager
          GraphicsDeviceManager graphics;

          // sprite 
          SpriteBatch spriteBatch;
          SpriteFont spriteFont;
          int t = 59;

          // main array 
          Diamond[,] Board = new Diamond[10, 10];
          public bool endgame = false;

          // texture use for gems
          Texture2D texture;
          Texture2D tDiamond;

          // render target 2D

          // vector position of texture and text
          Vector2 texturePosition = Vector2.Zero;
          Vector2 textPosition = Vector2.Zero;
          Vector2 textPosition2 = Vector2.Zero;
          Vector2 textPosition1 = Vector2.Zero;
          Vector2 textPosition3 = Vector2.Zero;

          // pBuffer array point check destroy
          Point[] pBuffer = new Point[2];

          // index of pBuffer array
          int BufferIndex = -1;
          int Circle = 0;
          public long point = 0;
       

        public EntityManager(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
            
        }
       

        public override   void Initialize()
        {
             // set random
            tDiamond = Game.Content.Load<Texture2D>("Images/Diamond");
            RscMgr.GetInstance().tDiamond = tDiamond;
             Random ran = new Random((int)DateTime.Now.Ticks);
             int n = 7;
             int value;
             for (int i = 0; i < 10; i++)
             {
                 for (int j = 0; j < 10; j++)
                 {
                     value = ran.Next(0, n - 1);
                     Board[i, j] = new Diamond(value, j, i);
                 }
             }

             // destroy the same rows and collums so that in main array have no more rows need to destroy
             for (int i = 0; i < 10; i++)
             {
                 for (int j = 0; j < 8; j++)
                 {
                     checkDestroy(i, j, false); // false in this means no add to point
                 }
             } // Code cũ tạo mới các viên lin cương.
             base.Initialize();
        }

        // HAM LOADCONTENT()
        protected override  void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // load content data

            // load content texture
            texture = Game.Content.Load<Texture2D>("Images/Sprites");

            // load content font
            spriteFont = Game.Content.Load<SpriteFont>("FontsBarsFont");

            // position for font
            textPosition.X = 30;
            textPosition.Y = 50;

            textPosition2.X = 100;
            textPosition2.Y = 450;

            textPosition1.X = 30;
            textPosition1.Y = 450;

            textPosition3.X = 200;
            textPosition3.Y = 450;
        }



        protected override void UnloadContent()
        {
            base.UnloadContent();
        }

        public override void Update(GameTime gameTime)
        {
            if (!endgame)
            {
                time += gameTime.ElapsedGameTime.Milliseconds;
                if (time > 1000)
                {
                    point -=1;
                    time = 0;
                }
                
                //collection of point touched
                TouchCollection touchCollection = TouchPanel.GetState();
                if (BufferIndex >= 1)
                {
                    if (!checkDestroy(pBuffer[0].X, pBuffer[0].Y, true) && !checkDestroy(pBuffer[1].X, pBuffer[1].Y, true))
                    {
                        if (
                           ((pBuffer[0].X - pBuffer[1].X) == -1 && (pBuffer[0].Y - pBuffer[1].Y) == 0) ||
                           ((pBuffer[0].X - pBuffer[1].X) == 1 && (pBuffer[0].Y - pBuffer[1].Y) == 0) ||
                           ((pBuffer[0].X - pBuffer[1].X) == 0 && (pBuffer[0].Y - pBuffer[1].Y) == 1) ||
                           ((pBuffer[0].X - pBuffer[1].X) == 0 && (pBuffer[0].Y - pBuffer[1].Y) == -1)
                           )
                        {

                            // wait 1 second for swap again
                            //base.Draw(gameTime);
                            Thread.SpinWait(3000);

                            // swap
                            int Temp = Board[pBuffer[0].X, pBuffer[0].Y].id;
                            Board[pBuffer[0].X, pBuffer[0].Y].id = Board[pBuffer[1].X, pBuffer[1].Y].id;
                            Board[pBuffer[1].X, pBuffer[1].Y].id = Temp;
                            //base.Draw(gameTime);
                        }
                    }
                    BufferIndex = -1;
                }

                // each point 
                foreach (TouchLocation touchLoc in touchCollection)
                {
                    if ((touchLoc.State == TouchLocationState.Pressed))
                    {
                        int j = (int)((touchLoc.Position.X ) / 60);
                        int i = (int)((touchLoc.Position.Y - 200)/ 60);
                        if (j < 8 && i < 10 && i >= 0)
                        {
                            for (int ii = 0; ii < 10; ii++)
                            {
                                for (int jj = 0; jj < 8; jj++)
                                {
                                    if (Board[ii, jj].state == DIAMOND_STATE.DS_ROTATING) Board[ii, jj].SetState(DIAMOND_STATE.DS_IDLE);
                                }
                            }

                            Board[i, j].SetState(DIAMOND_STATE.DS_ROTATING);
                            BufferIndex++;
                            {
                                pBuffer[BufferIndex].X = i;
                                pBuffer[BufferIndex].Y = j;
                            }
                        }
                    }

                }
                if (BufferIndex >= 1)
                {
                    if (
                       ((pBuffer[0].X - pBuffer[1].X) == -1 && (pBuffer[0].Y - pBuffer[1].Y) == 0) ||
                       ((pBuffer[0].X - pBuffer[1].X) == 1 && (pBuffer[0].Y - pBuffer[1].Y) == 0) ||
                       ((pBuffer[0].X - pBuffer[1].X) == 0 && (pBuffer[0].Y - pBuffer[1].Y) == 1) ||
                       ((pBuffer[0].X - pBuffer[1].X) == 0 && (pBuffer[0].Y - pBuffer[1].Y) == -1)
                       )
                    {
                        int Temp = Board[pBuffer[0].X, pBuffer[0].Y].id;
                        Board[pBuffer[0].X, pBuffer[0].Y].id = Board[pBuffer[1].X, pBuffer[1].Y].id;
                        Board[pBuffer[1].X, pBuffer[1].Y].id = Temp;    
                    }
                }

                for (int i = 0; i < 10; i++)
                {
                    for (int j = 0; j < 8; j++)
                    {
                        Board[i, j].Update((float)gameTime.ElapsedGameTime.TotalSeconds);
                    }
                }
            }

            base.Draw(gameTime);
            base.Update(gameTime);
        }

        protected bool checkDestroy(int x, int y, bool count)
        {
            Random ran = new Random((int)DateTime.Now.Ticks);
            int n = 8;
            // int top, bot;
            // Board[x, y]
            int i = x;
            int j = y;
            int S1 = 1, S2 = 1;
            int Lowest = x;
            int[,] Temp = new int[10, 2];
            Temp[0, 0] = x;
            Temp[0, 1] = y;
            bool Same1 = true;
            bool Same2 = true;

            //
            // ROW
            //

            // left
            while (Same1 && j >= 1)
            {
                if (Board[i, j - 1].id == Board[i, j].id && Board[i, j - 1].id != 10)
                {
                    S1++;
                    j--;
                    Temp[S1 - 1, 0] = i;
                    Temp[S1 - 1, 1] = j;
                }
                else Same1 = false;
            }

            // reset value
            i = x;
            j = y;
            Same1 = true;

            // right
            while (Same1 && j < 9)
            {
                if (Board[i, j + 1].id == Board[i, j].id && Board[i, j + 1].id != 10)
                {
                    S1++;
                    j++;
                    Temp[S1 - 1, 0] = i;
                    Temp[S1 - 1, 1] = j;
                }
                else Same1 = false;
            }

            // checkdestroy
            if (S1 >= 3)
            {
                for (int h = S1 - 1; h >= 0; h--)
                {
                    for (int k = Temp[h, 0]; k >= 0; k--)
                    {
                        if (k > 0)
                        {
                            Board[k, Temp[h, 1]].id = Board[k - 1, Temp[h, 1]].id;
                        }
                        else
                        {
                            Board[k, Temp[h, 1]].id = ran.Next(0, n - 1);
                        }
                    }
                }
                if (count)
                    point += S1 * 10;
                for (int i2 = 0; i2 < 10; i2++)
                {
                    for (int j2 = 0; j2 < 8; j2++)
                    {
                        checkDestroy(i2, j2, count);
                    }
                }
                return true;
            }

            // 
            // COLUM
            //

            // above
            while (Same2 && i >= 1)
            {
                if (Board[i - 1, j].id == Board[i, j].id && Board[i - 1, j].id != 10)
                {
                    S2++;
                    i--;
                    Temp[S2 - 1, 0] = i;
                    Temp[S2 - 1, 1] = j;
                    if (i > Lowest)
                        Lowest = i;
                }
                else Same2 = false;
            }

            // reset value
            i = x;
            j = y;
            Same2 = true;

            // below
            while (Same2 && i <= 8)
            {
                if (Board[i + 1, j].id == Board[i, j].id && Board[i + 1, j].id != 10)
                {
                    S2++;
                    i++;
                    Temp[S2 - 1, 0] = i;
                    Temp[S2 - 1, 1] = j;
                    if (i > Lowest)
                        Lowest = i;
                }
                else Same2 = false;
            }

            // checkdestroy
            if (S2 >= 3)
            {
                for (int k = Lowest; k >= 0; k--)
                {
                    if (k - S2 >= 0)
                        Board[k, Temp[S2 - 1, 1]].id = Board[k - S2, Temp[S2 - 1, 1]].id;
                    else
                    {
                        Board[k, Temp[S2 - 1, 1]].id = ran.Next(0, n - 1);
                    }
                }

                // count score  
                if (count)
                    point += S2 * 10;

                // checkdestroy all
                for (int i2 = 0; i2 < 10; i2++)
                {
                    for (int j2 = 0; j2 < 8; j2++)
                    {
                        checkDestroy(i2, j2, count);
                    }
                }
                return true;
            }
            return false;
        }

        public override void Draw(GameTime gameTime)
        {
            //GraphicsDevice.Clear(Color.Black);
            if (!endgame)
            {
                spriteBatch.Begin();
                for (int i = 0; i < 10; i++)
                {
                    for (int j = 0; j < 8; j++)
                    {
                        if (Board[i, j].id < 7)
                        {
                            Board[i, j].Draw(spriteBatch);

                            //Rectangle dRect = new Rectangle(j * (60), i * (60) + 160, 64, 64);
                            //Rectangle sRect = Board[i, j].a.rect;
                            ////Rectangle sRect = new Rectangle((Board[i, j].id % 4) * (64 + 1), ((Board[i, j].id - 1) / 4) * (64 + 1), 64, 64);
                            //spriteBatch.Draw(tDiamond, dRect, sRect, Color.White);
                        }
                    }
                }

                spriteBatch.DrawString(spriteFont, TEXT + point, textPosition, Color.White, 0, Vector2.Zero, 2, SpriteEffects.None, 0);

                spriteBatch.End();
            }
        }
    }
}
